home *** CD-ROM | disk | FTP | other *** search
/ Belgian Amiga Club - ADF Collection / BS1 part 34.zip / BS1 part 34 / FredFish PD 307.adf / FileIO / FileIO.doc < prev    next >
Text File  |  1990-01-13  |  96KB  |  2,054 lines

  1. FileIO Requester
  2. User and Programmer Manual
  3. From the Amiga Programmer's Suite Book 1, by RJ Mical
  4. Copyright (C) 1987, Robert J. Mical
  5.  
  6. Additional notes concerning the requester library have been added by
  7. Jeff Glatt who converted the original C into an assembly language library.
  8.  
  9. This document describes the FileIO Requester library, both for users of
  10. the requester and for programmers who will utilize the library.
  11. The main sections of this document are:
  12.  
  13.    o  FROM THE USER'S POINT OF VIEW
  14.  
  15.    o  PROGRAMMER'S REFERENCE
  16.  
  17.    o  DEMO PROGRAM NOTES
  18.  
  19.    o  TECHNICAL REFERENCE
  20.  
  21.    o  USING THE AMIGA PROGRAMMER'S SUITE
  22.  
  23.    o  APPENDIX A:  FileIO Library Function Calls
  24.  
  25.  
  26.  
  27. ============================================================================
  28. === FROM THE USER'S POINT OF VIEW ==========================================
  29. ============================================================================
  30.  
  31. This section presents the FileIO Requester from the user's point of view.  
  32. This is a example of the sort of documentation that might be supplied to the
  33. end user of this FileIO Requester. Simply clip from here to the Programmer's
  34. section, and include this as a chapter in the user manual.
  35.  
  36.  
  37.  
  38. === The FileIO Requester ========================================
  39.  
  40.   This program employs a file requester based upon R.J. Mical's ProSuite
  41. unit, though this library implementation has been modified extensively.
  42.   The FileIO Requester allows you an easy way to select which file you want 
  43. to use for input or output.  The following describes how you go about using 
  44. the FileIO Requester.
  45.  
  46. The FileIO Requester consists of several parts:  
  47.  
  48.    o  the "Select a Name" list which allows you to choose a file name
  49.       simply by scrolling through a list of names until you find the one
  50.       you want, pointing at the name and clicking the left mouse button
  51.  
  52.    o  the OK! gadget which you use to acknowledge that the name you've 
  53.       chosen is the one you wanted
  54.  
  55.    o  3 string gadgets which allow you to type in the name directly rather
  56.       than using the "Select a Name" gadgets to find the file you want 
  57.  
  58.    o  a NEXT DISK gadget which allows you to examine one disk after another 
  59.  
  60.    o  the CANCEL gadget, which you use when you've decided that you don't
  61.       want to select a file after all
  62.  
  63. The "Select a Name" list presents you with a list of file names in the 
  64. current drawer. You use the mouse to scan easily through the list and select
  65. one of the filenames simply by pointing at it and clicking.  
  66.  
  67. The "Select a Name" feature consists of:
  68.  
  69.    o  a box of where some of the list of file names are displayed
  70.  
  71.    o  a slider which lets you scan quickly through the list of files
  72.  
  73.    o  an up gadget and a down gadget which allow you to move through the
  74.       list one filename at a time
  75.  
  76.  
  77. There are 3 types of entries in the list of file names.
  78.  
  79. At the top of the list are the file names that you can choose.  These names
  80. are listed in alphabetical order (case insensitive).  
  81.  
  82. At the bottom of the list there are special entries which allow you to move 
  83. around through the drawers of a disk, much like you move around through 
  84. drawers on the Workbench display.  
  85.  
  86. The entries that start with the ">>>>" characters allow you to "open" a 
  87. drawer and examine the names of the files in that drawer.  For example, when
  88. examining a Workbench disk, at the bottom of the list you would find an
  89. entry that looked like ">>>> Demos" which means that you can go into the
  90. drawer named "Demos".  If you selected ">>>> Demos" you would see, after a
  91. short pause, a new list of file names:  the names of the files that are in
  92. the "Demos" drawer.  
  93.  
  94. In the "Demos" drawer you would also find a special entry,
  95. "<<<< PRIOR DRAWER".  If you select this entry, you will move back to 
  96. the drawer that contained your current drawer.  
  97.  
  98. An alternate way to change drawers is to type the name of the drawer you 
  99. want in the string gadget labeled "Drawer". It is located beneath the 
  100. filename list.  You select the gadget, type in the name, and hit return.
  101. If you type the name of a drawer which does not exist, the FileIO will send
  102. you back to the root directory of that disk. The length of the string that
  103. you type into the drawer gadget is limited to 132 characters. Since AmigaDOS
  104. limits the length of all file, drawer, and disk names to 30 characters, this
  105. means that you can safely nest drawers (one inside of another) up to four
  106. drawers deep. Beyond that, you should make sure that your drawer names are
  107. less than 30 chars each. The FileIO will not allow you to go any deeper after
  108. the drawer gadget has 132 chars in it.
  109.  
  110. Once you have a list of file names to choose from in the file name box, 
  111. there's a slider gadget to help you scroll around through the names. The
  112. slider is to the right of the file names.  It has a knob which you move to
  113. scroll through the names.  The knob will be different sizes depending on the
  114. number of names in the file list.  If the knob is small, this means that you 
  115. can see only a small number of the total file names. The smaller the knob,
  116. the more names there are to see.  On the other hand, if you can see all the
  117. names in the list, the knob will fill up the entire slider and you won't be
  118. able to move it.
  119.  
  120. To view the file names, you "grab" the slider's knob and move it up and down.  
  121. You grab the knob by pointing at it and pressing and HOLDING the left mouse
  122. button.  When you have grabbed the knob, you can move the pointer and scan
  123. quickly through the list of file names.
  124.  
  125. Also, you can view the list of names one page at a time by clicking to either
  126. side (but not on) the slider's knob.  If you want fine control of your
  127. movement through the file list, the up and down arrows let you adjust the
  128. list of names one name at a time. If you hold the mouse button down while on
  129. top of either arrow, the filenames will scroll in that direction. When you
  130. release the button, scrolling stops, but if instead you move off the arrow
  131. before releasing, the scrolling continues. Auto-scroll will continue until
  132. you click on a scrolling filename, or until the end of the list is reached.
  133.  
  134. Once you have found the file name that you want to choose, you select it by
  135. pointing at it and clicking.  When you do this, the name will be highlighted
  136. and it will appear in a box labeled "Name" beneath the list.  When you've
  137. decided that this is really the name you wanted to choose, click on the OK!
  138. gadget.  Another way to tell the program that you're sure you want to select
  139. a certain file name is by double-clicking on the file name in the same way
  140. that you double-click on a Workbench icon.  Double-clicking is exactly the
  141. same as selecting a name and then OK!
  142.  
  143. If you don't want to use the "Select a Name" feature, you can select a name
  144. by clicking on the string gadget labeled "Name", typing the desired filename, 
  145. and then hitting return or clicking on the OK! gadget.  Hitting return after
  146. typing the name you want is the same as selecting OK! You can select and
  147. type into the string gadgets at any time. You don't have to wait for the
  148. wait pointer to change before you hit return! If you type in the name of a
  149. disk that is not mounted, and then refuse to insert it into the drive when
  150. AmigaDOS asks you for it, the FileIO switches to another disk that is
  151. mounted (if another floppy exists).
  152.  
  153. To view the files of a different disk, select the NEXT DISK gadget. When you
  154. do, the name of the next disk is displayed in the Disk string gadget and the
  155. disk is then searched.  If this disk isn't the one you wanted, you can press
  156. NEXT DISK again even though you may be seeing the wait pointer.  You can
  157. press NEXT DISK quickly as many times as you want until you see the name of
  158. the disk you want in the Disk gadget. If you prefer, you can also type the
  159. name of the disk you want directly into the Disk string gadget. If the disk
  160. you want to examine is not in the drive, you may remove the disk that the
  161. requester has last examined (after the light goes out of course), and insert
  162. the desired disk in that drive. Now wait for the requester to automatically
  163. update its display. After inserting a disk, the requester will automatically
  164. redraw the list.
  165.    Alternately, you may select a new disk by clicking the RIGHT MOUSE button.
  166. The filenames will be replaced by a list of all the mounted volumes (or
  167. devices). The name of the disk that you are currently examining will be
  168. highlighted. You can scroll through this list of disk names using the slider.
  169. When you see the disk name that you would like to examine, click the LEFT
  170. MOUSE button on it. The FileIO will then display the contents of that disk.
  171.  
  172.  You might notice that the ZZZ-cloud wait pointer looks a little different 
  173. from the ones you're used to on the Amiga.  The FileIO Requester's ZZZ-cloud
  174. pointer has a small tab at the top left which allows you to continue 
  175. pointing and making selections even though the ZZZ-cloud is displayed.  
  176. The FileIO Requester's ZZZ-cloud tells you that it's working, but it
  177. doesn't make you wait.
  178.  
  179.   You might notice also that the file names start appearing one by one 
  180. alphabetically in the list.  You can select one of these names even before
  181. all of the names have been added to the list, though this can be a bit
  182. tricky as they move around a lot.  While the list is being built, you can
  183. use the slider to look at what names have already been added. If you see the
  184. name that you want to select, you can stop the building of the file name
  185. list by clicking on a spot inside the requester but outside of all the
  186. gadgets. For instance, if you click above (but not on) the OK! gadget, this
  187. will stop the list from being constructed. Then you can select the name you
  188. want as usual.  To restart the building of the file name list, click on
  189. either the Drawer or Disk string gadget and hit return. You can also stop
  190. the display of filenames temporarily by grabbing and holding the scroll
  191. gadget. When you release, the display will continue.
  192.  
  193.   For some reason, the requester may not be able to open. Maybe another
  194. program is already displaying it. Only one program can be displaying it at a
  195. time. Or perhaps you have used up too much memory. In either case, instead
  196. of a requester, you will see this prompt in the title bar of the window.
  197.  
  198.   Filename >
  199.  
  200.   This will be followed by a cursor and whatever filename you last chose
  201. with the requester. You must now type in the complete name (including the
  202. drive and drawer names) as you would in the CLI. For example,
  203.  
  204.   Extras:BasicDemos/ConvertFD
  205.  
  206.   If the window is not full size, you should move it to the upper left
  207. corner of the monitor display, and resize it to fully open. Then press any
  208. cursor key to redisplay the cursor. If there was no previous filename, then
  209. you will see the ":" current directory sign. Move the cursor past this and
  210. type in the filename that you wish to save or load if it is on the current
  211. disk. Otherwise, you need to type the name of the disk upon which the file
  212. can be found. The disk name goes in front of the ":", and the drawers and
  213. filename go after the ":". (If the file is on the current disk, and in the
  214. current drawer, you only need to type the filename. Otherwise, you must
  215. specify which disk and drawer you really want.) If the filename that is
  216. initially displayed is the one that you want, simply press RETURN.
  217.  
  218.   You can use the cursor keys to move about in the filename, deleting charac-
  219. ters with the delete or backspace keys. If there is any text extending beyond
  220. the border of the window, you can scroll to it using the cursor keys.
  221.   Holding the shift key while pressing the cursor keys will move to the
  222. beginning and end of the typed filename.
  223.   When you are satisfied with your choice, hit RETURN. Otherwise, hit the
  224. escape key to cancel.
  225.  
  226.   You have the facility to "customize" the requester for each application.
  227. After the requester comes up, the function keys have the following purposes:
  228.  
  229. F1 - Operates the same as selecting the Next Disk gadget.
  230. F2 - Toggles between using the volume name or the device name of the floppy.
  231.      For example, if you place your WorkBench disk in the internal drive
  232.      and you are using volume names, "WorkBench 1.3:" will appear for the
  233.      Disk name. If using device names, "DF0:" will appear instead.
  234. F3 - Any filename that ends in ".info" will not be displayed. To disable
  235.      this feature, select F3 again.
  236. F4 - Only displays filenames that end with a phrase that you provide.
  237.      You will be prompted to enter a string in the title bar of the window.
  238.      If for example, you typed .library, then the requester would display
  239.      all drawers, but only those files that end with .library. The word
  240.      need not be an extension. You could also specify that only files that
  241.      end with the word, picture, be displayed. To disable this feature,
  242.      select F4 again. The program that you are using must support this
  243.      feature for it to work. If the program doesn't support it, F4 will do
  244.      nothing.
  245. F5 - This toggles ON/OFF the facility for double-clicking on a filename to
  246.      select it as your final choise. If OFF, you must click on the
  247.      filename, and then select OK! before the requester will accept your
  248.      choise as final. Otherwise, 2 quick clicks will be the same thing.
  249. F6 - This will cause the requester not to initially reconstruct the filename
  250.      list on subsequent uses. The advantage is that the next time the req-
  251.      uester comes up, the names will appear immediately. The disadvantage is
  252.      that if you save a file, it will not appear in the list until you turn
  253.      this feature back on (momentarily anyway). Turn it on/off by pressing F6.
  254. F7 - WorkBench matching ON/OFF. If ON, this only displays those names that
  255.      end in .info (just like WorkBench does). Also, a prompt asks you whether
  256.      you want only those names that are TOOLS, PROJECTS, or any kind. An example
  257.      of a TOOL is a program that you can run, like NotePad. An example of a
  258.      PROJECT is a data file, like a note you might write using NotePad.
  259.      The names of disks are never displayed in the filename list.
  260. F8 - Alphabetize feature ON/OFF. When ON, the filenames are alphabetized in
  261.      the display. When OFF, newer files are listed at the top of the display.
  262. F9 - Same as the CANCEL gadget.
  263. F10 - Same as the OK! gadget.
  264.  
  265.  When you customize the requester, it only affects that one application, so
  266. different programs can have different "customized" requesters.
  267.  
  268.  
  269.  
  270. ============================================================================
  271. === PROGRAMMER'S REFERENCE =================================================
  272. ============================================================================
  273.  
  274. This section is for the programmer who wants to use the FileIO Requester 
  275. library routines in her or his program.
  276.  
  277. The Workbench names for DOS objects have been used in the FileIO Requester, 
  278. and are used throughout this document for simplicity.  For your reference, 
  279. a directory is referred to as a "drawer" and volumes, or DOS filesystem 
  280. devices, are referred to as "disks".
  281.  
  282. These are the subsections of this section:
  283.  
  284.    o  Basic Operation
  285.  
  286.    o  Multiple FileIO Structures
  287.  
  288.    o  Workbench-style Filename Operations
  289.  
  290.    o  Filtering by Extension
  291.  
  292.    o  No Icon (.info) files
  293.  
  294.    o  FileIO Flags
  295.  
  296.    o  DoFileIO() and DoFileIOWindow() are non-reentrant
  297.  
  298.    o  Procedure for Opening and Using the FileIO Requester library
  299.  
  300.    o  Displaying Lists of Strings (non-disk operation)
  301.  
  302.  
  303. ========================== Basic Operation ============================
  304.  
  305. The FileIO routines base all of their work on a data structure called 
  306. the FileIO structure.  You are allocated one of these structures when you
  307. call the GetFileIO() routine.  The structure is initialized with reasonable
  308. default values for you. Conversely, you can declare and pre-initialize a
  309. FileIO structure as long as all fields are set to zero or an appropriate
  310. value. At the very least, you must set the FileIO's Buffer field to point to
  311. where you want string input stored, and initialize the DrawMode, PenA, and
  312. PenB fields to desired values. The buffer size should be > = 202 bytes.
  313.  
  314. The FileIO structure is used when calling the DoFileIO() and DoFileIOWindow()
  315. routines, which are the routines that actually present the requester to
  316. the user and get the user's filename selection. DoFileIOWindow() is the same
  317. as DoFileIO() except that the former opens a window for the requester. With
  318. DoFileIO(), you must already have a window open.
  319.  
  320. There are several flags and data fields in the FileIO structure that you
  321. may choose to initialize before calling DoFileIO(). By setting or clearing
  322. these flags, you define how information is to be presented to the user.
  323. These flags are described below in "FileIO Flags". Also, the user can
  324. change these flags for each FileIO via the function keys.
  325.  
  326. The DoFileIO() function returns one of 2 values:
  327.  
  328. 1). The address of the buffer where the complete pathname (disk, drawer,
  329.     and filename as one, NULL-terminated string) has been stored. This
  330.     buffer will be the one that you supply in the FileIO's buffer field.
  331. 2). A -1 if the user selected the cancel gadget.
  332.  
  333. The DoFileIOWindow() function may return this additional value:
  334.  
  335. 3). A zero if the window didn't open.
  336.  
  337. You can call these routines any number of times with the same FileIO
  338. structure. Also, your program can have more than one FileIO structure at a
  339. time. An example of why you would want more than one FileIO structure: you
  340. might want to have separate structures for getting input filenames and
  341. output filenames from the user.  Another example:  you might have one
  342. structure for letting the user select text files and another for the
  343. selection of graphics files each with different options/features. Also,
  344. there are some lib routines that do not deal with disk file IO, but use the
  345. FileIO structure nonetheless and you might want a FileIO with a special
  346. string buffer for these routines.
  347.  
  348. Finally, when you're finished with your FileIO structure (usually not until
  349. your program is terminating) then you call ReleaseFileIO() to deallocate all
  350. the resources that it's accumulated. If the FileIO was obtained via
  351. GetFileIO(), this routine also frees it for you.
  352.  
  353.  
  354. ====================== DoFileIO() is non-reentrant ========================
  355.  
  356. The DoFileIO() routine is non-reentrant.  For the sake of memory efficiency,
  357. it uses global data and variables rather than creating local copies of these
  358. for each caller. What this means is that only 1 task can use the library
  359. functions DoFileIO() or DoFileIOWindow() at a time, though all other lib
  360. functions are re-entrant. If you attempt to call DoFileIO() or DoFileIOWindow()
  361. while another task is using it, the library will automatically prompt the
  362. user to type in the complete filename, instead of displaying the requester.
  363. The area where the user types in the filename is in the title bar of the
  364. window where the requester opened. The prompt
  365.  
  366.    Filename >
  367.  
  368.  will be displayed in the window's titlebar, along with a cursor. Several
  369. line editing features are supported including cursor key movement (with the
  370. ability to insert characters), backspace, delete, shift-right and shift-left
  371. cursor to the start and end of the string, and escape. The window's title is
  372. later restored. In fact, this feature of being able to use the title bar for
  373. getting user input can be used with your own prompts. It is a handy alterna-
  374. tive to having a string gadget (which takes up window space and also requires
  375. allocating several structures), plus allows for displaying custom prompts.
  376. The newest version of the lib lets the user scroll to any test beyond the
  377. boundaries of the window title bar borders.
  378.  Note that many tasks can open the library simultaneously, but only 1 can be
  379. displaying the FileIO requester at a given moment.
  380.   This redirection to entering the filename via the title bar is completely
  381. invisible to your application. Upon return from DoFileIO() or DoFileIOWindow()
  382. you will receive one of the 2 (or 3), previously described return values.
  383.  
  384.  
  385. ========== Interpreting the return value of DoFileIO() ================
  386.  
  387.   As mentioned before, there are 3 possible return values from DoFileIOWindow
  388. and 2 returns from DoFileIO(). If there is not enough memory for the window
  389. to open with DoFileIOWindow(), then the return value is 0 and the FileIO's
  390. Errno field = ERR_WINDOW. If this happens, you will have to find another way
  391. to get the filename. If you already have a window open, use DoFileIO(). This
  392. routine will never fail. Alternately, you might have the user type the path
  393. as he would from the CLI, and call ParseString() to put it in the FileIO.
  394.   If the user selects the CANCEL gadget, (or hits ESCAPE when entering the
  395. filename in the titlebar, or RETURN with no chars input), both routines will
  396. return -1.
  397.   In all other cases, the address of the FileIO's Buffer will be returned.
  398. This indicates that the user selected OK, or typed something in the string
  399. gadgets or title bar. This does not mean that the filename is valid for
  400. your purpose though. Let's assume that you called DoFileIO() from a load
  401. routine. Naturally, you want the user to select an existing file to load,
  402. but let's say that he types a non-existant file in the Name gadget or just
  403. selects a disk or drawer without eventually choosing a file before selecting
  404. OK. You can determine what the user did by examining 2 FileIO fields. The
  405. FileIO's Filename buffer contains just the filename portion of the complete
  406. path (separated from all the drawer and disk names). If this buffer is NULL,
  407. then the user did not select a filename. If the buffer is not NULL, then he
  408. either selected a filename, or typed one in. If he typed one in, how do
  409. you know if the filename exists? The FileIO's FileSize field will be 0 if
  410. the filename doesn't exist (or couldn't be examined because the user refused
  411. to mount the file's disk). In this case, you would abort the load. If the
  412. FileSize is not 0, then the file exists and this is how large it is in bytes.
  413. In conclusion, here are the steps you should take for a load routine:
  414.  
  415. 1). Call DoFileIO() with the FileIO's Buffer set to the address of your
  416.     path buffer, and the DrawMode, PenA, and PenB fields initialized.
  417. 2). Examine the return. If -1, then CANCEL. (If 0 for DoFileIOWindow, then
  418.     get the filename another way).
  419. 3). Check the FileIO's filename buffer for NULL. If NULL, then abort load
  420.     posting "This is not a loadable file."
  421. 4). Check the FileIO's FileSize field. If zero, post "File doesn't exist."
  422. 5). Otherwise, use the path buffer to open the file for reading.
  423.  
  424.  Here are the steps you should take for a save routine:
  425.  
  426. 1). Same as load routine step 1
  427. 2). Same as load routine step 2
  428. 3). Check the filename buffer for NULL. If NULL, then abort posting
  429.     "Did not supply a filename."
  430. 4). Check the FileSize field. If it's not 0, then the user must have selected
  431.     a filename that already exists on the chosen disk and in the specified
  432.     drawer. Post "File exists. Should we overwrite it?" Get a yes or no
  433.     response from the user to continue or abort.
  434. 5). Otherwise, use the path buffer to open the file for writing.
  435.  
  436.  
  437. ======================== Internal Error Handling ==========================
  438.  
  439.   The requester is set up so that if the user types in a non-existant disk
  440. name or refuses to mount the chosen disk, the req will default to any other
  441. mounted disk. If no disks mounted, then the default FILEIO_DISKNAME is ":".
  442. For example, assume that the user types "Leroy:" in the disk string gadget, 
  443. but the disk is not in any drive. AmigaDOS will prompt for that disk. If
  444. the user then CANCELs the system prompt, the FileIO req will display the
  445. contents of some other disk that is mounted, adjusting the string gadgets
  446. accordingly. In the case where no disks are mounted, the pathname buffer
  447. that is returned will not contain any disk name.
  448.   If the user types a drawer name that is not in the current dir level, the
  449. req will knock him back to the root of the current dir. For example, assume
  450. that the user is looking inside of a drawer called "TireBiter". There is no
  451. drawer called "George" inside here, but the user types this in the drawer
  452. string gadget nonetheless. The requester will clear ALL the drawer names,
  453. defaulting to the root of the disk.
  454.   The library will not return non-existant disk or drawer names. If you needed
  455. the requester to do this though (maybe you want to pass the path buffer to
  456. CreateDir) then the user should type the "new" drawer name by itself in the
  457. Name gadget. Conversely he could enter the string via the titlebar like so:
  458.  
  459.   WorkBench:Demos/Blort
  460.  
  461.  where you simply treat Blort as a dir name instead of a filename. The lib
  462. will copy Blort to the FileIO's Filename field nonetheless. Just check the
  463. FileSize field to make sure that there isn't a file already named this.
  464.   If there is some error in obtaining the disk name and it defaults to ":",
  465. then the returned pathname will not have a drawer name prepended to it.
  466. For example, say the user typed "df0:" in the drawer string gadget, but the
  467. drive was empty. The requester will automatically default to another mounted
  468. disk/device, etc, until one can be examined, or finally ":" is used. If the
  469. user then types "Papoon" in the Filename Gadget, the returned path will be:
  470.  
  471.   Papoon
  472.  
  473. which will be stored in the FileIO's Filename buffer if its a Filename, or
  474. the FileIO's Drawername buffer if it's a drawer. If it is a Filename that
  475. exists in the current dir, the FileSize will be its size in bytes.
  476.  
  477.  
  478. ================= Quick Display (NO_CARE_REDRAW) ================
  479.  
  480.   The data in the FileIO structure often remains valid between calls to
  481. DoFileIO(), so with subsequent calls a flag has been provided to avoid
  482. reconstructing the filename list. This allows the requester to appear very
  483. quickly because the usually-lengthy process of accessing the disk is avoided.
  484. Other times, it may be necessary to have the requester reconstruct its list
  485. of filenames (i.e. when a disk is changed or a file created/deleted by an
  486. application which does not communicate with the FileIO requester). Perhaps,
  487. as in a save routine, it may not be important to show the user what other
  488. recent files are on the disk as long as proper file protection is provided.
  489. The library uses the NO_CARE_REDRAW flag to discern whether to reconstruct
  490. the list, or simply to use the FileIO's previous names. If you set this flag,
  491. the old list is simply redrawn. Once you set this flag, the list will not
  492. be reconstructed on subsequent calls until you explicitly clear NO_CARE_REDRAW.
  493. (i.e. you always get the same, non-updated list unless the user changes dirs
  494. or disables the feature himself via the Function keys).
  495.    When GetFileIO() creates a FileIO structure for you, this flag is cleared
  496. to specify that the structure doesn't contain an updated list of filenames.
  497. Thus the first call to DoFileIO() causes the filename list to be constructed.
  498. After the call to DoFileIO() is the time to set the flag. You must do a bit
  499. of work if you wish to make use of this feature. You are obliged to watch
  500. for IDCMP events of class DISKINSERTED and to clear the NO_CARE_REDRAW flag
  501. in any of your FileIO structures whenever you see this event. The
  502. DISKINSERTED event occurs when the user has switched around the disks. When
  503. the user has changed disks, you can't be sure that your FileIO's filename
  504. list is still valid, so as a courtesy to the user you must cause the filename
  505. list to be reconstructed. In the case that some disk activity occurs in a
  506. program that doesn't use the FileIO library, you will never know about this
  507. activity. Also, if the disk is changed or files are created/deleted by some
  508. other task using the library, you will have no way to determine this. For
  509. these reasons, you may elect to forgo this feature entirely. If you don't use
  510. this feature, you need not bother looking for DISKINSERTED events. Because
  511. the library has been completely rewritten in optimized assembly, it doesn't
  512. take too long for the requester to construct its list anew. Also, the user
  513. can toggle this feature ON/OFF using function key 6 if he wants. The example
  514. applications don't use this feature. You can use the FileIO Requester library
  515. to get the name of a file to be used for output.  If you do, and the
  516. specified file doesn't currently exist, AmigaDOS will create it anew when
  517. you open it (mode NEWFILE). From the FileIO Requester point of view, this
  518. means that a file now exists that isn't in your FileIO list.  To get the name
  519. in the list, clear the NO_CARE_REDRAW (if it was SET). The next time that
  520. the FileIO structure is used for a call to DoFileIO() or DoFileIOWindow(),
  521. the new file name will appear alphabetized in with the other file names.
  522. Once again, this is not applicable if you don't ever set NO_CARE_REDRAW.
  523.    If you have more than one FileIO structure, remember that you must clear
  524. the NO_CARE_REDRAW flag in all of them whenever you see Intuition's
  525. DISKINSERTED IDCMP event class (if you're using the NO_CARE_REDRAW feature).  
  526. Also, regarding new disks, there's an extra procedure that you must follow.  
  527. If the user changes the disk while you've called DoFileIO() or DoFileIOWindow(),
  528. you won't actually see a DISKINSERTED event (as the event will have been 
  529. processed by the library before control is returned to you). So how will you
  530. know to clear the NO_CARE_REDRAW flag in your other structures?  Well, the
  531. library records the fact that a DISKINSERTED event was handled by setting
  532. the DISK_HAS_CHANGED flag in your FileIO structure. So on return from a call
  533. to DoFileIO() or DoFileIOWindow you should check to see whether your FileIO
  534. structure has the DISK_HAS_CHANGED flag set. If it does, you should clear
  535. the DISK_HAS_CHANGED flag in the structure and then clear the NO_CARE_REDRAW
  536. flag in all of your other FileIO structures.  This assures that when you
  537. call DoFileIO() with any of your other support structures, the filename lists
  538. will be reconstructed, as they should. Please note that all this needs to be
  539. done ONLY IF YOU'RE SETTING NO_CARE_REDRAW.
  540.  
  541.  
  542. =============== Workbench-style Filename Operations ====================
  543.  
  544. You can have file names appear in the FileIO Requester using the same rules
  545. that govern how files appear on the Workbench display, by using the Workbench
  546. .info file mechanism.  
  547.  
  548. To attempt to match Workbench patterns, you must set the WBENCH_MATCH flag
  549. in your FileIO structure, as described below.
  550.  
  551. The Workbench .info file mechanism is a detailed topic that will not be 
  552. delved into here.  Please read the Amiga ROM Kernel Manual for a description
  553. of the Workbench operation and data types.  What follows is a cursory
  554. description of the Workbench technique, which is described only well enough
  555. to explain how you can interact with it via your FileIO structure.  
  556.  
  557. The Workbench program examines the directory of a disk and displays icons
  558. for the files it finds that end with a ".info" suffix (hereafter referred to
  559. as .info files).  The file names displayed beneath the icons have the
  560. ".info" suffix removed.  The Workbench .info files contain information
  561. regarding what type of data is contained in the file (executable program,
  562. project data, et cetera).
  563.  
  564. You can choose to have only .info files displayed to the user (with the
  565. ".info" removed) in the same way that the Workbench does. You get this
  566. by setting the WBENCH_MATCH flag. Any executables without icons (.info files
  567. ) will not be displayed. The same is true of drawers.
  568.  
  569. If you wish, you can further filter the names that appear. There are two
  570. techniques that you can employ for filtering which file names will be added
  571. to the list:  you can ask for only those files that match a particular
  572. Workbench object type and only those files that match a particular tool type.  
  573.  
  574. You elect to match the object type by setting the MATCH_OBJECTTYPE flag in
  575. your FileIO structure.  The object types typically of interest are WBTOOL
  576. and WBPROJECT.  By selecting one of these 2 types, your filename list will
  577. consist only of executable files or data files respectively (except that all
  578. .info drawer names are always displayed). If this is confusing, refer to the
  579. ROM Kernel manual for a discussion of object types.  
  580.  
  581. You can also request to match a Workbench tool type.  By matching tool types,
  582. you can, for instance, have your file list display only those data files
  583. that were created by a specific application.  See the section entitled
  584. "The ToolTypes Array" in the Workbench chapter of the ROM Kernel manual for
  585. a description of how tool types work.  You elect to match tool types by
  586. placing a pointer to the ToolTypes text in the ToolTypes field of your FileIO
  587. structure. If this field is left zero, then the TOOLTYPES will be ignored.
  588.  
  589.  
  590. =========================== No Info Files ============================
  591.  
  592.   Setting the INFO_SUPPRESS flag is exactly the opposite of Workbench
  593. matching. All files that end in .info will be ignored, and not displayed.
  594. This is handy if the user doesn't have a .info file to go with every file
  595. that he wishes to peruse. With WB MATCH, those files would not be displayed.
  596. With INFO_SUPPRESS set, they would be displayed but no .info files would
  597. clutter the display. This gives the impression of WB MATCH while enabling
  598. files without icons to also be seen. On the down side, that means that the
  599. user will see ALL files without icons including those that are best left
  600. alone (i.e. translator.library). All drawers are displayed regardless.
  601. When the user makes his selection, the .info is not added to the pathname.
  602.  
  603.  
  604. ==================== Filtering by Extension =====================
  605.  
  606.    Sometimes, you may have an application that only wants to see filenames
  607. that end with a certain string (i.e. ".iff"). You can specify an extension
  608. by storing the address of this string in the Extension field of the
  609. FileIO. Also, you need to specify the length (don't count the terminating
  610. NULL byte) and store this value in the ExtSize field. For the preceding
  611. example, the length would be 4 (counting the .). Finally, you must set the
  612. EXTENSION_MATCH flag. If the EXTENSION_MATCH flag is clear, the extension
  613. fields will be ignored. In this way, you can quickly enable and disable the
  614. feature with the one flag. Only the files that END with this extension (case
  615. insensitive) will be displayed. Incidentally, this need not be a real exten-
  616. sion. You can match any ending at all. For example, you could only display
  617. those files that end with the string "picture". In this case, the length
  618. would be 7. If you set the EXTENSION_MATCH flag, then clear the INFO_SUPPRESS
  619. flag. Because only those files that end in your specified extension are seen,
  620. .info files won't be displayed anyway (unless your specified extension is
  621. ".info" in which case you'll get nothing but .info files. An icon editor,
  622. maybe?) All drawers will be displayed regardless. Please note that the
  623. extension string that you supply MUST HAVE ALL LETTERS IN LOWER CASE.
  624.   In order for the user to take advantage of this feature via the F4 key,
  625. you must set up the FileIO for it. First you must supply a buffer for the
  626. user's typed extension. Place the address in the FileIO's Extension field.
  627. The buffer must be at least 20 bytes long. Don't enable the EXTENSION_MATCH
  628. flag.
  629.   If you don't want the user to take advantage of extension match, then
  630. clear the EXTENSION_MATCH flag AND zero the Extension pointer field. There
  631. is the possibility that you may have supplied an Extension to be matched
  632. and while the requester was displayed, the user changed the match string.
  633. For this reason, the buffer should always be at least 20 bytes if you use
  634. this feature. Also, don't assume that the returned filename is definitely
  635. ending with the extension you initially passed. If the user changed the
  636. match string, it won't be the same extension. Also, you should re-initialize
  637. your extension buffer string each time before you call DoFileIO(). The
  638. returned pathname and FILEIO_FILENAME buffer have the extension added.
  639.  
  640.  
  641. ========================== FileIO Flags ===========================
  642.  
  643.  Remember that the user can always adjust these himself with the function
  644.  keys. For this reason, you might simply go with the defaults.
  645.  
  646. NO_CARE_REDRAW
  647.     This flag designates whether the filename data contained in the 
  648.     FileIO is to be reconstructed before initially drawing the requester.
  649.  
  650. USE_DEVICE_NAMES
  651.     When you leave this flag CLEAR, the AmigaDOS volume names will
  652.     be used for the disk names in the requester.  If you SET
  653.     this flag, the device names will be used instead. The default is to
  654.     follow the Workbench convention and use volume names.
  655.  
  656. DISK_HAS_CHANGED
  657.     If the user changes the disk while the FileIO Requester is being
  658.     displayed, this flag is set in the FileIO structure. The only time you
  659.     must pay attention to this flag is when you have set the NO_CARE_REDRAW
  660.     flag. If you find that DISK_HAS_CHANGED has been set, you must clear
  661.     that flag in this FileIO structure and then clear the NO_CARE_REDRAW
  662.     flag in all of your FileIO structures.
  663.  
  664. DOUBLECLICK_OFF
  665.     Normally, the user can double-click on a filename to select it.  
  666.     You may choose to disable this feature, for instance, when you want the
  667.     user to be very certain about the filename selection (perhaps if the
  668.     file is about to be destroyed, or something equally drastic). To disable
  669.     double-clicking, set the DOUBLECLICK_OFF flag.  Then the user will have
  670.     to explicitly select OK! or type the filename and hit return for the
  671.     selection to be made.
  672.  
  673. WBENCH_MATCH
  674.     You set this flag to specify that you want Workbench-style .info file
  675.     logic to be used when constructing the filename list. This flag is
  676.     cleared when your FileIO structure is first created.
  677.  
  678. MATCH_OBJECTTYPE
  679.     When you set this flag (and the WBENCH_MATCH flag), the MatchType field
  680.     of your FileIO structure will be compared with the do_Type field of the
  681.     .info file's DiskObject structure.  If they match, the file will be 
  682.     displayed.  Both the MATCH_TOOLTYPE and the MATCH_OBJECTTYPE flags can
  683.     be set at the same time.
  684.  
  685. MULTIPLE_FILES
  686.     Set this flag for multiple filename selection. All selections must be in
  687.     the same directory. You must examine the EntryFlags (selected bit) of
  688.     each Entry structure to determine which files were selected. This flag
  689.     cannot be changed by the user unless an application allows him to do so.
  690.  
  691. INFO_SUPPRESS
  692.     All .info files are suppressed from the display if you SET this.
  693.  
  694. EXTENSION_MATCH
  695.     Filters filenames that end with a certain string if you SET this.
  696.  
  697. CUSTOM_HANDLERS
  698.              Allows adding custom handlers to the internal library
  699. handlers of GADGETUP, GADGETDOWN, MOUSEMOVE, RAWKEY, DISKINSERTED,
  700. and initial REQSET. You can supply an additional handler for any and all of
  701. these events that will be invoked along with the internal library handler
  702. (or in place of it). Once you call DoFileIO(), the handlers will be installed
  703. and active until the requester ends. Set or Clear this flag before calling
  704. DoFileIO(). If the requester can't open or is being used by another task,
  705. the user will get titlebar entry, and your handlers will be ignored.
  706.  
  707. NO_ALPHA
  708.      When clear, the filenames are alphabetized in the display. When SET,
  709. newer files are listed at the top of the display.
  710.  
  711. SPECIAL_REQ
  712.      Allows using the FileIO requester to display lists of strings not
  713. relating to disk drive operations.
  714.  
  715.  
  716. ======================= RAM DISK bug ============================
  717.  
  718.    There seems to be a bug in 1.2 AmigaDOS. For some reason, whenever one
  719.    attempts to get an AmigaDOS Lock on the volume named "RAM DISK:" a
  720.    software error occurs.  The problem doesn't necessarily lie in AmigaDOS, 
  721.    but the truth is that the error occurs with little provocation 
  722.    of AmigaDOS (for instance:
  723.         dir "RAM DISK:"
  724.    can and does crash the Amiga).  Though 1.3 resolves this bug, the FileIO
  725.    code provides a work-around for 1.2 by changing "RAM DISK:" to "RAM:"
  726.    which locks successfully and does not crash the machine. This solution
  727.    has a problem:  if the user has given the name  "RAM DISK:" to some
  728.    non-RAM: disk (such as a floppy) then this fix will fail and the floppy
  729.    named "RAM DISK:" wouldn't be seen. This isn't too bad of a problem,
  730.    because if the user has been silly enough to name a floppy "RAM DISK:"
  731.    the user is probably experiencing lots of other problems already and this
  732.    will provide just one more reason why one shouldn't name a floppy 
  733.    "RAM DISK:" don'cha know.
  734.  
  735.  
  736. ======================= Free Disk Space ================================
  737.  
  738.   The FileIO's FREEBYTES field indicates how many free bytes remain on the
  739. disk that the user has chosen. This is useful for a save routine. After all,
  740. you wouldn't want to start saving a 230K file to a disc that only has 229K
  741. free. Unfortunately, AmigaDOG always says that the RAM DISK: has 0 bytes
  742. free. Actually, it has as many bytes free as mem that is available. Whenever
  743. the user selects RAM: or RAM DISK:, the FileIO's FREEBYTES is set to
  744. 0xFFFFFFFF (the largest size possible). If you encounter this condition, you
  745. may wish to use Exec's AvailMem to determine if you can do the save.
  746.  
  747.  
  748. ========== Procedure for Using the FileIO Requester library ===========
  749.  
  750. This section presents a step-by-step procedure for utilizing the FileIO
  751. Requester library with your own program.
  752.  
  753. Copy the requester.library into the libs directory of your boot disk. For
  754. workbench users, double-click on the inclosed program "CopyLib" and place
  755. your Workbench disk in the drive when you see the DOS requester. CopyLib
  756. will display the FileIO requester if all went well. Select the requester's
  757. CANCEL and exit the program by closing the window.
  758.  
  759. You have to include FileIO.h in every C module that refers to your FileIO
  760. structure.
  761.  
  762.     #include "FileIO.h"
  763.  
  764.  For assembly language users, (WOW! We hardly ever get real support for
  765.  programming on the Amiga), include FileIO.i
  766.  
  767. Open the library via a call to exec's OpenLibrary and store the pointer at
  768. a variable called RequesterBase (MUST BE CALLED THIS FOR C PROGRAMMERS).
  769.  
  770.    if (!(RequesterBase = (APTR) OpenLibrary("requester.library", 0L)))
  771.    exit(0);
  772.  
  773. Declare a pointer to a FileIO structure (initialized to 0), and then fill
  774. that pointer with the address of one of the structures.
  775.  
  776.     struct FileIO *myFileIO = 0;
  777.  
  778.     myFileIO = GetFileIO();
  779.  
  780.                 <<<< IF USING NO_CARE_REDRAW >>>>>
  781. Your NewWindow structure should have the DISKINSERTED flag set along with 
  782. your other IDCMP flags.  Whenever you receive a DISKINSERTED event, you 
  783. should clear the NO_CARE_REDRAW flag (if SET) in every FileIO structure you
  784. control.  The following code could be added to the case switch where you 
  785. handle IDCMP events.
  786.  
  787.     switch (imessageclass)
  788.         {
  789.         case DISKINSERTED:
  790.             /* You should clear the NO_CARE_REDRAW flag
  791.              * whenever you detect that a new disk was 
  792.              * inserted.
  793.              */
  794.             if (myFileIO)
  795.                 ClearFlag(myFileIO->Flags, NO_CARE_REDRAW);
  796.             break;
  797.         }
  798.  
  799. Alternately, you may elect to leave NO_CARE_REDRAW clear in which case the
  800. requester display will be updated every time it is used and you won't need
  801. to bother with receiving DISKINSERTED events.
  802.  
  803.   Set the FileIO's Buffer field to the address of a buffer that you have
  804. allocated. This is where the complete path will be constructed for you.
  805. (i.e  Disk:drawer1/drawer2...etc/filename ) Also initialize the FileIO's
  806. DrawMode, PenA, and PenB. You might also want to set the FileIO's X and Y
  807. fields where the requester will open within your window (relative upper left).
  808. If using DoFileIO(), and your window is not full size, include a sizing
  809. gadget so that if the user needs to type via the title bar he can expand it.
  810.  
  811. When you want to present the FileIO Requester to the user, call DoFileIO() or
  812. DoFileIOWindow(). If these routines return the address of the passed buffer
  813. where you want the full path name to be stored, the user did not cancel the
  814. operation, nor was there an error in opening the window (for DoFileIOWindow
  815. only). A -1 and 0 will be returned respectively for the two error conditions.
  816. The following code is an example of presenting the FileIO Requester to the
  817. user and then reacting to the result.
  818.  
  819.   /* This set-up need only be done once, though you can change them later */
  820.  
  821.    UBYTE buffer[204];
  822.  
  823.    myFileIO->Buffer = buffer;
  824.    myFileIO->DrawMode = JAM1;
  825.    myFileIO->PenA = 1;
  826.    myFileIO->PenB = 0;
  827.  
  828.   /* ================================================================ */
  829.  
  830.    if (myFileIO)
  831.    {
  832.        result = (DoFileIO(myFileIO, window));
  833.     if (result==&buffer[0])
  834.        {
  835.             /* Here, do something like read or write the file.
  836.              */
  837.            if (writefile)
  838.            {
  839.             if (myFileIO->FileName[0])
  840.               {
  841.                if (!myFileIO->FileSize)
  842.                {
  843.                 /* Open the file (MODE_NEWFILE) */
  844.                 /* Write the file */
  845.                 /* Close the file */
  846.                }
  847.                 /* Otherwise, tell the user that he's about to overwrite */
  848.               }
  849.                 /* Error in entering filename */
  850.            }
  851.            if (readfile)
  852.            {
  853.             if (myFileIO->FileName[0])
  854.               {
  855.               if (myFileIO->FileSize)
  856.                {
  857.                 /* Open the file (MODE_OLDFILE) */
  858.                 /* Read the file */
  859.                 /* Close the file */
  860.                }
  861.                 /* Otherwise, tell the user that the file doesn't exist */
  862.               }
  863.                /* Not a loadable file */
  864.            }
  865.        }
  866.      if (result==0)
  867.        {
  868.           /* This only happens if DoFileIOWindow() bombs. Call DoFileIO() */
  869.        }
  870.    /* Otherwise, CANCEL must have been selected. Never mind. */
  871.    }
  872.  
  873. Finally, when you're done with your FileIO structure (usually when
  874. your program is exiting), you can free up the structure and its resources
  875. with a simple call to ReleaseFileIO(), like this:
  876.  
  877.     if( RequesterBase ) ReleaseFileIO(myFileIO);
  878.  
  879. Also, you need to close the library upon exit.
  880.  
  881.     if( RequesterBase ) CloseLibrary( RequesterBase );
  882.  
  883.   When you link your C program, you'll need to assemble and link with
  884. FileInterface.asm. This is the usual assembly poot needed by C programs in
  885. order to call assembly language libraries. You want efficiency, write in
  886. assembly. Assembly programmers can simply use the _LVO library offsets as
  887. provided in FileIO.i. See the example applications for details.
  888.  
  889.   ONE FINAL NOTE: The lib needs to trap RIGHT MOUSE buttons for displaying
  890.   the list of disk names. When exiting, the lib clears the RMBTRAP bit of
  891.   your window's flags, so if you had it set before calling DoFileIO(), then
  892.   you'll have to set it again upon return by going to the Flags field of
  893.   your window structure and setting bit #16.
  894.  
  895.  
  896. ============ USING THE REQUESTER TO DISPLAY LISTS OF STRINGS =============
  897.  
  898.    There may be times when you need to display a list of strings in a
  899. requester so that a user can scroll around the list via the mouse and
  900. choose an item in the list. The amount of code and IDCMP hassle of construct-
  901. ing such a requester can certainly be considerable, especially if you want to
  902. include a Prop scroll bar, scroll arrows, a string gadget, CANCEL and OK
  903. gadgets, etc.
  904.    The latest version of the FileIO requester library has a feature whereby
  905. you can use the lib's requester to display your list of strings. The lib
  906. handles all user interaction, list display, and IDCMP. You simply set the
  907. SPECIAL_REQ flag of the FileIO before calling DoFileIO() or DoFileIOWindow()
  908. and the requester will display your list of strings. The requester is no
  909. longer a disk I/O tool. In fact, the Disk and Drawer string gadgets are re-
  910. moved from the display, and the NextDisk gadget no longer has anything to do
  911. with switching dirs.
  912.    The user can employ the Prop and Arrow gadgets (with auto-scroll) to scroll
  913. through the list of strings. The size of the Prop's knob reflects the per-
  914. centage of visible strings just like in the disk I/O version.
  915.    The user can click on any string to make it the currently selected one,
  916. and it will be highlighted and copied to a string gadget below. Or the user
  917. can type his selection directly into the string gadget. A double-click on
  918. a string will end the requester with that string as the chosen one.
  919.    The chosen string will be copied to the FileIO's Filename buffer. Note
  920. that with SPECIAL_REQ, you do not need a Pathname buffer. (In fact, the
  921. FileIO's BUFFER field will be overwritten.)
  922.    With SPECIAL_REQ, DoFileIO() or DoFileIOWindow will return the following:
  923.  
  924.   1). A -1 if the user selected the CANCEL gadget.
  925.   2). A -2 if the library was being used by another task (i.e. the same
  926.       note about non-reentrant code applies here).
  927.   3). A 0 if there is a problem opening the FileIO window (if DoFileIOWindow
  928.       doesn't open, or the requester doesn't open).
  929.   4). The address of the FileIO's Filename buffer (i.e. where the selected
  930.       string is copied) if all went well and the user selected OK, or double-
  931.       clicked on a string, or typed in his selection in the Name gadget.
  932.  
  933.    So how do you give your list of strings to the lib? There are 2 functions,
  934. NewEntryList() and AddEntry() that you use to make the list.
  935. Here are the passed parameters.
  936.  
  937.    EntryNum = AddEntry(ID_num, StringAddress, FileIO);
  938.       d0                 d1         a0          a1
  939.  
  940.    NewEntryList(FileIO);
  941.                   a1
  942.  
  943.    Each FileIO can have its own list attached to it. NewEntryList frees
  944. any previous list (if one exists) that was made for the passed FileIO. For
  945. this reason, you should call NewEntryList first before using AddEntry to
  946. add strings. You can then add strings to the list by subsequent calls
  947. to AddEntry. (AddEntry adds the one passed string into the list. The list is
  948. alphabetized as each string is added to it so that the strings are always
  949. displayed in alphabetical order, unless you set the NO_ALPHA flag. With
  950. NO_ALPHA, each entry is added to the tail of the list.) ID_num is some value
  951. that you want associated with the string. When the user selects that string,
  952. it is copied into the FileIO's Filename buffer and the ID is copied into the
  953. FileIO's FileSize field. This ID is a LONG, and can be any value you desire
  954. (i.e. maybe even a pointer to some data structure associated with that string). The only restriction is that ID cannot be -1 (i.e. 0xFFFFFFFF).
  955.    The returned EntryNum is where the string has been alphabetically placed
  956. in the list (i.e. the first string in the list returns 0). If you receive
  957. a negative number from AddEntry(), this means that there wasn't enough memory
  958. to add the string to the list. Actually, AddEntry copies the string, and
  959. adds the copy to the list, so you need not keep the original string after it
  960. is added to the list.
  961.    When you finally call ReleaseFileIO(), any list associated with the FileIO
  962. is freed.
  963.    Here is how you might create a list with the following 3 items and display
  964. it in the FileIO requester:
  965.  
  966.    /* You should have opened the requester lib and allocated a FileIO */
  967.  
  968.    if (myFileIO)
  969.    {
  970.        NewEntryList(myFileIO);
  971.        error = AddEntry(1L, "This is One", myFileIO);
  972.        if (error<0) break;
  973.        error = AddEntry(2L, "Two", myFileIO);
  974.        if (error<0) break;
  975.        error = AddEntry(3L, "Three", myFileIO);
  976.        if (error<0) break;
  977.  
  978.        result = (DoFileIO(myFileIO, window));
  979.     if (result==myFileIO->FileName)
  980.        {
  981.             /*  FileName buffer contains the string, and FileSize the ID
  982.              */
  983.        }
  984.      if (result==0)
  985.        {
  986.           /* This only happens if DoFileIOWindow() bombs. Call DoFileIO() */
  987.        }
  988.      if (result==-2)
  989.        {
  990.           /* This happens if someone is using the library. Come back later */
  991.        }
  992.    /* Otherwise, CANCEL must have been selected. Never mind. */
  993.    }   
  994.  
  995.    There is a possibility that the user may type a string that is not in the
  996. list, directly into the Name gadget. Before exiting, the requester lib will
  997. check if the string is in the list. If not, the string is copied to the
  998. FileIO FileName buffer as before, but the FileSize field is set to -1. A
  999. FileSize of -1 means "this string isn't in the list". That is why you should
  1000. not assign an ID of -1 to any string. The lib ignores the case of the string
  1001. when comparing items in the list (i.e. "Amiga" and "amIGA" are the same),
  1002. but it does not trim away any leading or trailing spaces.
  1003.  
  1004.    With SPECIAL_REQ, the "Next Disk" gadget can be a custom gadget for your
  1005. use. You place into the FileIO's FileIOText field a pointer to the string
  1006. that you want displayed in the gadget. This string should be no more than 11
  1007. characters (not counting the end NULL). You should pad the head of the
  1008. string with spaces to properly center inside the gadget. You should also
  1009. store in the FileIO's FileIORoutine field a pointer to a routine that is to
  1010. be executed everytime the user releases the mouse over the custom gadget.
  1011. The library calls this routine passing the FileIO and Window (that the
  1012. requester opened in), and the Requester Structure.
  1013.  
  1014.    BOOL  yourRoutine(Requester, Window, FileIO)
  1015.                        a5         a3      a2
  1016.  
  1017.    This function should return TRUE to end the requester, or FALSE to continue.
  1018. If FALSE, the FileIO display will be refreshed when your function returns. (In
  1019. case your custom routine added/removed something from the list, or changed
  1020. lists). If you return TRUE, the requester will end with the FileIO's Errno
  1021. field will be set to ERR_APPGADG.
  1022.    If your FileIO's FileIORoutine field is set to NULL when you call DoFileIO,
  1023. the custom gadget is removed from the display.
  1024.  
  1025.    Finally, there is a routine that you can use to determine if a certain
  1026. string is in the list.
  1027.  
  1028.    entryNum = IsEntryThere(String, FileIO)
  1029.      d0                      a0      a1
  1030.    where String is the address of the string you wish to check for.
  1031.    This returns the entryNum (like AddEntry) of the string if it is found
  1032.    in the list, or a -1 if it is not in the list. For assembly programmers,
  1033.    if found, the address of the Remember structure is returned in a0.
  1034.  
  1035.  
  1036. ====================== Filename and Custom Lists =====================
  1037.  
  1038.    The list of filenames (or custom list created via AddEntry) is created using
  1039.    the Intuition function, AllocRemember. The "anchor" of the list is the
  1040.    FileIO's FileList field. So each string has its own Remember structure. The
  1041.    Remember's rm_Memory points to my own Entry structure. An Entry structure
  1042.    looks like this:
  1043.  
  1044. struct Entry   {
  1045.    LONG   EntryID;
  1046.    UBYTE  EntryFlags;  /* Don't alter this! */
  1047.    UBYTE  EntryString[size of the string not counting end NULL];
  1048.    };
  1049.  
  1050.    In asm,
  1051.  
  1052. EntryID     dc.l 0
  1053. EntryFlags  dc.b 6
  1054. EntryString dc.b [the bytes comprising the NULL-terminated string]
  1055.  
  1056.      I have redefined the Remember structure as a FileEntry structure since
  1057. that is easier to reference:
  1058.  
  1059. struct FileEntry {
  1060.     struct FileEntry  *nextEntry;
  1061.    ULONG  EntrySize;
  1062.    struct Entry     *filePart;
  1063.    };
  1064.  
  1065.  Don't use sizeof on these structures. The library makes them for you. The 3rd
  1066.  field of the Entry structure is a variable length, NULL-terminated string.
  1067.  This structure has been defined simply so that you can get access to the
  1068.  EntryID, EntryFlags, and EntryString. These structures are used for both
  1069.  custom lists and the list of filenames. For filenames, each filename has a
  1070.  FileEntry structure. Its EntryID is the filesize. Bit #7 of the EntryFlags
  1071.  is set if the filename was selected by the user. The EntryString is the
  1072.  NULL-terminated filename (separated from its dir). When the SPECIAL_REQ
  1073.  flag is set, the Entry's EntryID is your passed ID to AddEntry().
  1074.  All the FileEntry structures are linked together, and the FileIO's
  1075.  FileList field points to the first FileEntry in the list.
  1076.  
  1077.    You can use one FileIO to alternately display several custom lists. The key
  1078. is to properly set the FileIO's NameCount, NameStart, CurrentPick, and FileList
  1079. fields before calling DoFileIO(). You should make a list as in the above
  1080. example, and then copy the FileList field to some global. Then zero out the
  1081. FileList field. Do this for all your lists. Now when you want to display one
  1082. list, pass the appropriate global to a routine that does the following:
  1083.    1). Clear the FileList field.
  1084.    2). Call NewEntryList() (to initialize the NameStart and CurrentPick)
  1085.    3). Set the FileIO's NameCount to the number of items in the list
  1086.    4). Set the FileIO's FileList to the passed global.
  1087.    5). Set the SPECIAL_REQ flag. (If it wasn't set previously.)
  1088.    6). Call DoFileIO()
  1089.    7). Clear the FileList field.
  1090.  
  1091.   Here's a C function to implement the above. It returns TRUE if all went
  1092. well, and FALSE if error or user cancel.
  1093.  
  1094. BOOL ShowList(ListAddr,NumOfItems,window,fileio)
  1095. struct Remember *ListAddr; /* the contents of the FileIO's FileList field
  1096.                               after you made the list with AddEntry(). */
  1097. SHORT NumOfItems;          /* number of entries in Remember List */  
  1098. struct Window *window;
  1099. struct FileIO *fileio;
  1100. {
  1101.    UBYTE *address;
  1102.  
  1103.    fileio->FileList = 0;  /* you stored the original value in the global ListAddr
  1104.                              after making the list */
  1105.    NewEntryList(fileio);
  1106.    fileio->NameCount = NumOfItems;
  1107.    fileio->FileList = ListAddr;
  1108.    SetFlag(fileio->Flags, SPECIAL_REQ);
  1109.    address = DoFileIO(fileio, window);
  1110.    fileio->FileList = 0; 
  1111.    if( address <= 0 )
  1112.        return( FALSE );
  1113.    else
  1114.       return( TRUE );
  1115. }
  1116.  
  1117.    When exiting your program, you must de-Allocate all the lists. For each,
  1118.    1). Set the FileIO's FileList to the passed global.
  1119.    2). Call NewEntryList()
  1120.  
  1121.  
  1122. void FreeProgList(fileio, filelist)
  1123. struct FileIO *fileio;
  1124. struct Remember *filelist;
  1125. {
  1126.    fileio->FileList = filelist;  /* original value you previously stored in global
  1127.                                    after making the list */
  1128.    NewEntryList(fileio);
  1129.    fileio->FileList = 0;
  1130. }
  1131.  
  1132.    Consult the examples, CustomList, for how to use SPECIAL_REQ.
  1133.  
  1134.  
  1135. ========================= Multiple Selections ===========================
  1136.  
  1137.   You can allow the user to make multiple selections from a custom list or the
  1138. filename list by setting the FileIO's MULTIPLE_FILES flag. When the user
  1139. clicks on a name, it will be highlighted. The user can then select more
  1140. filenames, with all of them simultaneously selected. The library sets bit
  1141. #7 of each selected file's Entry structure's EntryFlags. If a user clicks on
  1142. a filename that is already selected, then the filename is de-selected. Note
  1143. that double-clicking on a filename still can terminate the requester. The
  1144. last selected name is the one that appears in the FileIO's FileName buffer.
  1145.   When the user double-clicks, or selects CANCEL or OK, the requester ends.
  1146. At this point, you must go through the FileIO's FileList, examining each
  1147. Entry structure's EntryFlags for bit #7 set to determine which files were
  1148. selected. The caveat is that all files must be in the same directory because
  1149. the EntryString does not contain the full path, only the filename. (The path
  1150. can be constructed with the FileIO's Disk and Drawer buffers.)
  1151.   There is a library function to aid in locating the selected files:
  1152.  
  1153.   FileEntry = RetrieveEntry( FileEntryPtr, FileIO );
  1154.       d0                          a0         a1
  1155.  
  1156.   FileEntryPtr should point to a FileEntry structure in the FileIO's FileList
  1157. or be set to 0. If 0, this routine locates the first selected FileEntry
  1158. structure in the FileList, updates the passed FileEntryPtr to point to that
  1159. structure, and returns that address. The next time that this function is
  1160. called, FileEntryPtr will not be 0, and so this function will return the next
  1161. selected FileEntry structure, etc. When there are no more selected files, a 0
  1162. is returned and the FileEntryPtr is cleared.
  1163.  
  1164.   Another function:
  1165.  
  1166.   ClearEntries(FileIO);
  1167.                  a1
  1168.  
  1169.   clears the selected bit of all EntryFlags in the FileIO's FileList. This is
  1170. useful for clearing selections after a custom list has been presented to the
  1171. user, or for when the user has set NO_CARE_REDRAW.
  1172.  
  1173.   If the user types a filename directly into the Filename gadget, the library
  1174. will NOT check if the filename is in the current list and set its selected
  1175. bit if so. You can determine whether the filename exists in the current dir
  1176. by the value of the FILEIO_FILESIZE field as before. For SPECIAL_REQ, the
  1177. library DOES set the selected bit if the entered text is one of the displayed
  1178. choises.
  1179.  
  1180.    Consult the examples for how to use MULTIPLE_FILES.
  1181.  
  1182. =============================================================================
  1183. === DEMO PROGRAM NOTES ======================================================
  1184. =============================================================================
  1185.  
  1186. This section briefly describes the demo programs that drive some of the
  1187. FileIO Requester library's features. There is a C demo, an assembly demo,
  1188. and an AmigaBasic demo (no joke).
  1189.  
  1190. If you invoke the C or asm demos without a second argument, a window will be
  1191. opened in the Workbench screen.  If you invoke these demos with any second
  1192. argument, a hi-res screen will be opened for the requester window.
  1193.  
  1194. The C demo uses two FileIO structures to demonstrate the techniques that you
  1195. should use when managing multiple FileIOs. These techniques include processing
  1196. DISKINSERTED events and discovering on return from DoFileIO() that the
  1197. DISK_HAS_CHANGED flag is set. (As long as you're using the NO_CARE_REDRAW
  1198. feature). The first support structure, fileio1, is used in its vanilla state
  1199. as created by GetFileIO().  The other support structure, fileio2, is
  1200. initialized to do Workbench-style .info file handling where the filename
  1201. list will consist of only .info objects of type WBPROJECT. Also, fileio1
  1202. uses volume names and the other uses device names. You activate fileio1 when
  1203. you click the right mouse button. You activate fileio2 when you press any
  1204. key. Finally, when you do any of the selection techniques where you accept 
  1205. your selection, the pathname to your selection is displayed in a FileIO
  1206. autorequester. If you choose CANCEL to end the FileIO process, nothing happens.
  1207. To stop the program, click on the window close gadget (when the requester
  1208. is not displayed).
  1209.  
  1210. The assembly demo only uses 1 FileIO structure. There is a menu to
  1211. demonstrate various features. You should manually deselect the features
  1212. you want disabled, and select those that you want enabled. For example,
  1213. select CUSTOM to see how a custom handler is installed for the REQSET event.
  1214. Also, this program can look for files that only end in certain strings if
  1215. you select the EXTENSION menu item. When you enable the extension feature,
  1216. the application uses the PromptUserEntry() function. Notice how the prompt
  1217. appears in the window titlebar with a cursor. You can type in the string
  1218. that you want to match, and hit return. Now when you call up the requester,
  1219. only those filenames that end in that extension will be displayed (along
  1220. with any dirs). This works just like the F4 Function key option.
  1221.    Also of interest is the Multiple menu item which toggles MULTIPLE_FILES.
  1222. With this on, note how several files can be clicked and selected. When you
  1223. select OK, the asm example then prints out the pathbuffer, followed by all
  1224. files selected. Note that the selected files do not contain the full path.
  1225.  
  1226.  
  1227. The amigabasic demo asks the user if he wants to display only those files
  1228. with a certain extension, and inputs the extension. Otherwise, it suppresses
  1229. all .info files. It then copies the pathname to a string variable which can
  1230. be better utilized for basic manipulation. Also this demos a few of the
  1231. library's autorequester functions. When running this program, the included
  1232. bmap for the FileIO requester library must be in the same directory.
  1233.  
  1234. Additionally, there are examples to demonstrate using the requester to dis-
  1235. play custom lists of strings.
  1236.  
  1237.  
  1238. ========================================================================
  1239.                    INSTALLING CUSTOM HANDLERS
  1240.  
  1241.  You can install custom handlers for any of several events that might occur
  1242. in the requester. You need to set the CUSTOM_HANDLERS flag of the FileIO, and
  1243. fill the FileIO's HandlerBlockPtr field with the address of a HandlerBlock
  1244. structure. The HandlerBlock structure (defined in FileIO.h) holds the
  1245. addresses of the handlers for REQSET, DISKINSERTED, GADGETDOWN (and UP),
  1246. RAWKEY, and MOUSEMOVE. If you have no handler for a particular event, NULL
  1247. its HandlerBlock field. Each FileIO can have its own custom handlers.
  1248.   For REQSET, and DISKINSERTED, if your handler returns a 1, then the
  1249. library's internal handler will be skipped. Otherwise, the library routine
  1250. will be executed if you return a 0.
  1251.   For GADGETDOWN and GADGETUP, your handler will be called only if the Gadget
  1252. ID is not one of the requester's gadgets. Your handler will be passed the ID
  1253. in d0 (as well as other parameters). Your handler should return a 0 in order
  1254. to continue, or a 1 if you wish to end the requester. (You can check that
  1255. your custom handler ended the requester if the FileIO's Errno = ERR_APPGADG).
  1256. The only two requester gadgets that the library no longer controls are the CANCEL
  1257. and OK gadgets. Control of these two is passed to your custom handler. These
  1258. two gadgets have IDs of 32672 and 32673 respectively. If you receive either
  1259. of these IDs, you should return a 1. On the other hand, you could simply
  1260. cause these gadgets to be ignored by returning a 0. In any event, your
  1261. handler will have to return a 1 eventually in order to exit the requester,
  1262. or the user would have to type the Filename in the Filename string Gadget.
  1263. Do not use gadget IDs between 32672 to 32682 as these are reserved by the
  1264. library.
  1265.   For MOUSEMOVE, the events are "collected" (i.e. you only receive one event
  1266. when the user stops moving the mouse). Also, you won't receive MOUSEMOVE when
  1267. the user is operating the requester's scroll (prop) gadget. Your handler
  1268. doesn't need a return value.
  1269.   For RAWKEY, you won't receive any function keys. No return value is needed.
  1270.  
  1271.  The requester calls your handler with the following items in these
  1272. registers:
  1273.  
  1274.    a2 - the address of your FileIO
  1275.    a3 - the address of the window in which the requester is open
  1276.    a4 - the IAddress of the event (not valid for REQSET or DISKINSERTED)
  1277.    d6 - MouseX position (for RAWKEY handler, this is the Code instead)
  1278.    d7 - MouseY position (for RAWKEY handler, this is the Qualifier)
  1279.    d2 - Seconds
  1280.    d5 - Micros
  1281.    d0 - (need not be saved) For GADGETUP and DOWN, the gadgetID
  1282.         For RAWKEY handler, the ascii value as returned from DecodeRawkey()
  1283.  
  1284.  You MUST save these registers if you plan on altering them.
  1285.     If your handler is written in C (yech!), I've provided a mechanism for
  1286. receiving these parameters passed on the stack like all good, inefficient C
  1287. programs should. Let's face it, C just doesn't have enough power to do the
  1288. sophisticated, efficient things that we do in assembly. But if you'd like to
  1289. fool yourself into thinking otherwise, I've tried to accomodate your
  1290. delusions. After filling in the HandlerBlock's pointers to the desired
  1291. routines, you must call SetFileIOHandlers(HandlerBlock). This routine
  1292. will see to it that your handler receives the following parameters except
  1293. where previously noted.
  1294.  
  1295.  BOOL yourHandler(GadgID,Seconds,Micros,MouseX,MouseY,FileIO,Window,IAddress);
  1296.  
  1297.   Note that GadgID is the ascii value (UWORD) for the RAWKEY handler.
  1298.  
  1299.   Unfortunately, unlike the assembly implementation, if you want to have
  1300. different FileIO's with unique custom handler routines, you'll have to
  1301. call SetFileIOHandlers() before each call to DoFileIO(). Hey, you're writing
  1302. in C, so you should be used to giving up some flexibility.
  1303.   If you're using Manx small data model, you'll probably have to call geta4
  1304. or savea4 (whatever). a4 will definitely not have the base of your program's
  1305. data section. These are the types of problems you should expect if you allow
  1306. a C compiler to determine 68000 register usage. Also, since register a6 is
  1307. "reserved" for library base vectoring on the Amiga, the C interface to the
  1308. library does not save this register. If your compiled program crashes because
  1309. of this, its time to buy a better compiler, or perhaps solve these headaches
  1310. once and for all with an assembler.
  1311.  
  1312. struct HandlerBlock {
  1313.    APTR  StartUpCode;       /* Called when the requester first opens */
  1314.    APTR  DiskInsertedCode;  /* Called whenever a disk is inserted */
  1315.    APTR  GadgetCode;        /* Called whenever a gadget UP or DOWN */
  1316.    APTR  KeyCode;           /* Called whenever a rawkey occurs */
  1317.    APTR  MouseMoveCode;     /* Called when the mouse is moved */
  1318.    };
  1319.  
  1320. assembly:
  1321.   dc.l AddrOfStartCode
  1322.   dc.l AddrOfDiskInsertCode
  1323.   dc.l AddrOfGadgetCode
  1324.   dc.l AddrOfRawkeyCode
  1325.   dc.l AddrOfMouseMoveCode
  1326.  
  1327.    Please note that you should use DoFileIO() as opposed to DoFileIOWindow()
  1328. if using custom handlers.
  1329.  
  1330. =============================================================================
  1331. === TECHNICAL REFERENCE =====================================================
  1332. =============================================================================
  1333.  
  1334. The FileIO files include:
  1335.  
  1336.    requester.library      the actual library (slightly < 10K in size)
  1337.    manual                 The documentation. You've obviously found it.
  1338.    FileIO.h               includes for an C application using the library
  1339.    FileInterface.asm      glue routines for a C application to use the
  1340.                           library. (poot) Expects all integers passed 32bit
  1341.    FileIO.i               assembly programmer's include file
  1342.    main.c                 an application in C
  1343.    CustomList.c           an C demo using SPECIAL_REQ
  1344.    Test.asm               an application in assembly
  1345.    CustomList.asm         an asm application using SPECIAL_REQ
  1346.    StartUp.asm            the startup code for the assembly examples
  1347.    TestFileIO             an executable of the assembly application
  1348.    MakeTest               execute this script file to make the asm example
  1349.    BasicFileIO            an AmigaBasic application (do you believe me now?)
  1350.    BasicString            an AmigaBasic demo of SPECIAL_REQ
  1351.    requester.bmap         the bmap file for AmigaBasic
  1352.    requester_lib.fd       the fd file used to make the bmap file
  1353.    CopyLib                a utility to copy libraries to a boot disk
  1354.  
  1355.  
  1356. ================= USING THE AMIGA PROGRAMMER'S SUITE =======================
  1357.  The following is the message that appeared with RJ Mical's ProSuite code
  1358. on Fred Fish Disc #107. That version of FileIO was not a library. It was a
  1359. C code module that needed to be compiled and linked with your application.
  1360. At this point, the code for this library is significantly different than
  1361. the original, and quite incompatible with R.J's Includes and Defines. Also,
  1362. there are differences in both functionality and features. But R.J. started
  1363. the ball rolling so....
  1364.  
  1365. The Amiga Programmer's Suite Book 1 is copyrighted but freely distributable.
  1366. All copyright notices and all file headers must be retained intact.
  1367. The Amiga Programmer's Suite Book 1 may be compiled and assembled, and the 
  1368. resultant object code may be included in any software product.  However, no 
  1369. portion of the source listings or documentation of the Amiga Programmer's 
  1370. Suite Book 1 may be distributed or sold for profit or in a for-profit
  1371. product without the written authorization of the author, RJ Mical.
  1372.  
  1373. If you use the Amiga Programmer's Suite, I wouldn't mind if you gave me 
  1374. some mention somewhere.
  1375. Good luck!  Program hard, program well.    -RJ Mical
  1376.  
  1377. Make lots of money and become a arrogant, self-serving pain-in-the-ass.
  1378. -Jeff Glatt (my personal philosophy is a bit more philanthropic than RJ's)
  1379.  
  1380.  
  1381. === APPENDIX A:  FileIO Function Calls ======================================
  1382.  
  1383. CONTENTS:
  1384.    AddEntry()
  1385.    AutoMessage()
  1386.    AutoMessageLen()
  1387.    AutoPrompt3()
  1388.    AutoFileMessage()
  1389.    ClearEntries()
  1390.    DecodeRawkey()
  1391.    DoFileIO()        ;only 1 task at a time
  1392.    DoFileIOWindow()  ;only 1 task at a time
  1393.    GetFullPathname()
  1394.    GetFileIO()
  1395.    GetRawkey()
  1396.    IsEntryThere()
  1397.    NewEntryList()
  1398.    ParseString()
  1399.    PromptUserEntry()
  1400.    ReleaseFileIO()
  1401.    ResetBuffer()
  1402.    RetrieveEntry()
  1403.    SetWaitPointer()
  1404.    TypeFilename()
  1405.    UserEntry()
  1406.  
  1407.  
  1408. ««««««««««««««««««««««««««« FILENAME FUNCTIONS »»»»»»»»»»»»»»»»»»»»»»»»»»»»»»
  1409.  
  1410. *********************** DoFileIO(), DoFileIOWindow() **********************
  1411.  
  1412. NAME
  1413.     DoFileIO  --  Gets a file name for input/output from the user
  1414.     DoFileIOWindow() -- The same, but opens a window for the requester.
  1415.  
  1416. SYNOPSIS
  1417.     ULONG address = DoFileIO(fileio, window);
  1418.             d0                a0      a1
  1419.     ULONG address = DoFileIOWindow(fileio, screen);
  1420.             d0                      a0      a1
  1421.  
  1422. FUNCTION
  1423.     This routine creates a filename requester which allows the user to browse
  1424.     through the AmigaDOS filesystem and select one of the filenames found
  1425.     there.
  1426.  
  1427.     The fileio argument is a pointer to a FileIO structure, which is allo-
  1428.     cated and initialized via a call to GetFileIO(), or declared in your
  1429.     application.
  1430.     You may preset the FileIO parameters before calling this routine, 
  1431.     or you may leave them set at their default values.  See the FileIO
  1432.     documentation and include files for complete details.
  1433.  
  1434.     The window argument is the pointer to the window structure returned
  1435.     by a call to Intuition's OpenWindow() function.  As this routine
  1436.     opens a requester and requesters open in windows, you must have
  1437.     already opened a window before calling this routine, even if it's
  1438.     a window opened for no other purpose than to call this routine.
  1439.     DoFileIOWindow() is provided to circumvent this problem. It simply opens
  1440.     a window on the passed screen before calling DoFileIO, and closes it
  1441.     upon exit. By setting screen to NULL, the window opens on the WorkBench
  1442.     screen. Also, you might use DoFileIOWindow if you wanted a requester
  1443.     that could be moved or depth arranged by the user in an existing screen.
  1444.     The title that appears in the window will be gotten from the address in
  1445.     the FileIO's Title field.
  1446.  
  1447.     You must initialize the FileIO's Buffer field to hold the address of a
  1448.     buffer where the full pathname string (i.e. disk:drawer.../filename) will
  1449.     be constructed. The size should be no less than 202 bytes. Also, the
  1450.     FileIO's DrawMode, PenA, and PenB fields should be set to the values
  1451.     you want restored when the requester closes.
  1452.  
  1453.     This routine returns a 0 if DoFileIOWindow's window couldn't open, a -1
  1454.     if the user selected CANCEL, or the address of the FileIO's Buffer if
  1455.     all went well and the user selected a filename. The full path name will
  1456.     have been constructed in the buffer. The filename itself will have
  1457.     all leading and trailing blanks removed (in case the user typed in a
  1458.     filename with extraneous spaces) and stored in the FileIO's FileName[].
  1459.     Likewise, the disk and drawer names can be found in the text
  1460.     fields DiskName[] and DrawerName[] of the FileIO. You can always call
  1461.     GetFullPathname() to build the pathname from the separate fields of the
  1462.     FileIO.
  1463.  
  1464.     There's a *lot* more to be said about this function.  Please 
  1465.     read the documentation.
  1466.  
  1467.     NOTE:  This routine is not re-entrant.  What this means is that if some
  1468.     other task is calling DoFileIO() or DoFileIOWindow(), this routine
  1469.     will automatically call TypeFilename() for the 2nd application.
  1470.  
  1471. INPUTS (for DoFileIO)
  1472.     fileio = pointer to a FileIO structure, as allocated
  1473.         via a call to GetFileIO()
  1474.  
  1475.     window = pointer to a Window structure, as created via a call
  1476.         to Intuition's OpenWindow()
  1477.  
  1478. RESULT
  1479.     0 if an error in opening DoFileIOWindow() window. You will not get this
  1480.       error for DoFileIO()
  1481.    -1 if the user selected CANCEL
  1482.     the address of the Buffer if all went well and a file was selected. Also
  1483.     for assembly programmers the end of the string is in a1 like GetFullPathname.
  1484.  
  1485. BUGS
  1486.     Clears the RMBTRAP bit of Window's Flags.
  1487.  
  1488.  
  1489. ********************* GetFileIO() ************************
  1490.  
  1491. NAME
  1492.     GetFileIO  --  Allocate and initialize a FileIO structure
  1493.  
  1494.  
  1495. SYNOPSIS
  1496.     struct FileIO *GetFileIO();
  1497.  
  1498.  
  1499. FUNCTION
  1500.     Allocates and initializes a FileIO structure for use with
  1501.     calls to DoFileIO(), DoFileIOWindow(), TypeFileName(), PromptUserEntry().
  1502.  
  1503.     You may want to further initialize the structure before calling these
  1504.     routines. At least the FileIO's Buffer, DrawMode, PenA, and PenB fields
  1505.     should be initialized. Instead of allocating a FileIO via this routine,
  1506.     you may declare one globally or statically as long as all fields are
  1507.     initialized to zero or an approprite value.
  1508.  
  1509.     When you're done with the structure, call ReleaseFileIO() regardless of
  1510.     whether it was allocated or declared to free up resources.
  1511.  
  1512. INPUTS
  1513.     None
  1514.  
  1515. RESULT
  1516.     If all goes well, returns the address of a FileIO structure.
  1517.     If anything goes wrong (out of memory), returns NULL.
  1518.  
  1519.  
  1520. *********************** GetFullPathname() *********************
  1521.  
  1522. NAME
  1523.     GetFullPathname  --  Build a file pathname using a FileIO struct
  1524.  
  1525.  
  1526. SYNOPSIS
  1527.     Buffer = GetFullPathname(FileIO, Buffer);
  1528.      d0                       a0       a1
  1529.  
  1530. FUNCTION
  1531.     Builds the text for a pathname using the FileName[], DrawerName[] and
  1532.     DiskName[] fields of the specified FileIO structure after the structure
  1533.     has been used in a successful call to DoFileIO(), DoFileIOWindow(), or
  1534.     TypeFilename(). Writes the text into the Buffer. 
  1535.  
  1536. INPUTS
  1537.     FileIO = the address of a FileIO structure
  1538.     Buffer = address of the buffer to receive the file pathname
  1539.  
  1540. RESULT
  1541.     The address of the passed buffer. Also, for assembly programmers the
  1542.     address of the terminating NULL is in a1 so you can quickly determine
  1543.     the string length by subtracting d0 from a1 with the result in a1.
  1544.  
  1545.  
  1546. *********************** ParseString() *******************************
  1547.  
  1548. NAME
  1549.   ParseString - Separate a path string into separate components
  1550.  
  1551. SYNOPSIS
  1552.   ParseString(FileIO,String)
  1553.                 a0     a1
  1554.  
  1555. INPUTS
  1556.    The FileIO structure
  1557.    The address of the NULL-terminated path
  1558.  
  1559. FUNCTION
  1560.    This takes the NULL-terminated path as it would be typed on a CLI line
  1561.  
  1562.    Diskname:TopDrawer/....etc.../BottomDrawer/Filename
  1563.  
  1564.    and parses it for "weird" typos or non-existant disk or drawer names.
  1565.    Of course, there may not be any Disk or Drawer names. It then copies the
  1566.    individual components of the Disk, drawer, and filename to the FileIO's
  1567.    respective buffers, and sets the FILEIO_FILESIZE and FILEIO_FREEBYTES
  1568.    fields accordingly. (i.e. If the path turns out to be a drawer or disk
  1569.    only, then FileIO's Filename is NULLED and FileSize = 0. If a non-existant
  1570.    file, it copies the Filename to FileIO, but FileSize = 0. If it is a
  1571.    loadable file, it copies the Filename and sets FileSize accordingly.)
  1572.    The parsed result is placed into the FileIO's Buffer (cannot be the same
  1573.    buffer as the passed string).
  1574.       This is useful for processing the initial argv argument passed to
  1575.    _main for the StartUp code. It will initialize the FileIO buffers to
  1576.    this passed name, and set-up the FileSize and Filename buffer so that
  1577.    it can be determined what kind of object this is. Also, it makes it
  1578.    possible to use the same load routine for the initial passed argv as
  1579.    you would for DoFileIO() or TypeFilename(). For Basic programmer's this
  1580.    can be used to set up the FileIO based upon a string gotten via an Input
  1581.    statement.
  1582.  
  1583.  
  1584. ************************* ReleaseFileIO() **************************
  1585.  
  1586. NAME
  1587.     ReleaseFileIO  --  Release the FileIO structure and all local memory
  1588.  
  1589.  
  1590. SYNOPSIS
  1591.     ReleaseFileIO(fileio);
  1592.                     a1
  1593.  
  1594. FUNCTION
  1595.     Releases the FileIO structure by freeing all local memory attached
  1596.     to the structure and then freeing the structure itself if it is an
  1597.     ALLOCATED_FILEIO (i.e. not pre-initialized in your application).
  1598.     Restores the directory that was established when the FileIO was first
  1599.     sent to DoFileIO() or DoFileIOWindow(). (You should not unlock the
  1600.     initial dir that is contained in the FileIO's originalLock field.)
  1601.  
  1602. INPUTS
  1603.     fileio = the address of a FileIO structure
  1604.  
  1605. RESULT
  1606.     None
  1607.  
  1608.  
  1609. ;********************* TypeFilename() ***************************
  1610.  
  1611. NAME
  1612.     TypeFilename - Uses the window's titlebar to obtain the path name instead
  1613.                    of the file requester (an alternative). Displays the prompt
  1614.                    "Filename >"
  1615.  
  1616. SYNOPSIS
  1617.     buffer =TypeFilename(FileIO, Window);
  1618.                             a0     a1
  1619.  
  1620. FUNCTION
  1621.    If you really don't like the requester, and would prefer to have the
  1622.    user type in the full path via the window's title bar, then use this.
  1623.    Also, you might use this within a save routine so that the user has to
  1624.    deliberately type his choice. The pathname contained within the FileIO's
  1625.    Disk, Drawer, and Filename fields is what is initially presented to the
  1626.    user. This routine is automatically called if an application tries to
  1627.    call DoFileIO() or DoFileIOWindow() when another task is displaying the
  1628.    FileIO requester. Also called if there is not enough mem to open/display
  1629.    the requester. This routine sets up the FileIO's Disk, Drawer, Filename,
  1630.    FileSize, and FreeBytes fields in the same manner as DoFileIO so that
  1631.    you can interpret the results in exactly the same manner.
  1632.  
  1633. INPUTS
  1634.     Window = the address of a window
  1635.     FileIO = the FileIO structure
  1636.  
  1637. RESULT
  1638.   Returns the address of the FileIO's Buffer or a -1 if the user bailed
  1639.   out without entering anything. An ESC will return -1, but will store an
  1640.   ESC char ($1B) and then NULL char in the buffer.
  1641.  
  1642.  
  1643.  
  1644. «««««««««««««««««««««««««« RAWKEY STRING INPUT »»»»»»»»»»»»»»»»»»»»»»»»»»»»
  1645.  
  1646. ;*************************** DecodeRawkey() ***************************
  1647.  
  1648. NAME
  1649.     DecodeRawkey() - Takes the passed RAWKEY Code and Qualifier and returns
  1650.                      an ascii value based on the System KeyMap.
  1651.  
  1652. SYNOPSIS
  1653.     value = DecodeRawkey(Qualifier, Code);
  1654.                            d0        a1
  1655.  
  1656. FUNCTION
  1657.     Because there exists different Amiga keyboard configurations and alternate
  1658. keymaps, there are only 2 proper methods for your program to translate user
  1659. keystrokes into ascii chars:
  1660.  
  1661. 1). Use the console device.
  1662. 2). Use VANILLA_KEY IDCMP.
  1663.  
  1664.     The problem with #1 is that you have to deal with the console.device,
  1665. IO blocks, and Function, cursor, and other keys being translated as character
  1666. strings. Very UGLY!!!! The problem with #2 is that you don't receive Function,
  1667. cursor, or Help keystrokes. Very unfriendly!!! This routine solves both pro-
  1668. blems by managing the console device for you, and by "extending" the ascii
  1669. char set, it defines single ascii values for each Function, cursor, and Help
  1670. key.
  1671.  
  1672. INPUTS
  1673.   Code - the code field of a RAWKEY IntuiMessage
  1674.   Qualifier - the qualifier field of a RAWKEY IntuiMessage
  1675.  
  1676. RESULT
  1677.  The return is a UWORD (not a byte as is usually the case with ascii chars).
  1678.  This is because I have "extended" the ascii char set beyond hex FF in order
  1679.  to define values for the Function, cursor, and Help keys. A zero is returned
  1680.  if the key is undefined or if it is a KEYUP event.
  1681.  
  1682.  Plain Function keys return hex 100 to 109 for the 10 keys.
  1683.  The 4 cursor keys are hex 10A to 10D for UP, DOWN, RIGHT, and LEFT
  1684.      respectively.
  1685.  The Help key returns hex 10e.
  1686.  Shifted Function keys return hex 200 to 209.
  1687.  Shifted cursor keys are hex 20A to 20D.
  1688.  Shifted Help key is 20E.
  1689.  Alt Function keys are hex 400 to 409.
  1690.  Function keys with the left Amiga key held are hex 800 to 809.
  1691.  
  1692.  All other keys (and combos) return whatever value the System KeyMap contains
  1693. (except that all char strings are ignored and return 0).
  1694.  
  1695.  
  1696. ;*************************** UserEntry() ***************************
  1697.  
  1698. NAME
  1699.     UserEntry - Uses the window's titlebar to obtain user input.
  1700.  
  1701. SYNOPSIS
  1702.     buffer = UserEntry(charlimit, initBuffer, FileIO, Window);
  1703.                            d0         a1        a2      a3
  1704.  
  1705. FUNCTION
  1706.    This clears the window's titlebar, displays a cursor, and allows the user
  1707.    to type in chars up to the limit, or until CR or ESC is pressed. The NULL
  1708.    terminated result is placed in the FileIO's Buffer. When the charlimit is
  1709.    reached, the routine automatically terminates.  You must set the FileIO's
  1710.    PenA, PenB, and DrawMode fields so that these may be restored by the lib
  1711.    when the function is finished.
  1712.    The initBuffer string is what is presented to the user (and what he may
  1713.    edit). The passed window must have RAWKEY IDCMP set, and the FileIO's
  1714.    RawCode field set to 0 in order to use the default decoding routine,
  1715.    GetRawkey(). Otherwise, decoding will be redirected to the routine specified
  1716.    in the FileIO's RawCode field. (Maybe you want VANILLAKEY instead. Or
  1717.    maybe you also want to handle other IDCMP events while "inside" of UserEntry.
  1718.    GetRawkey disposes of all but RAWKEY events. Or maybe you've set up your
  1719.    own custom IDCMP port and RAW handling routine.) Regardless, your RawCode
  1720.    routine must go to the window's IDCMP port to get a message or wait if
  1721.    there is no message. It should handle all IDCMP messages except RAWKEY or
  1722.    VANILLAKEY. If one of these messages, exit with an UWORD representing the
  1723.    character as follows:
  1724.    $20 to $7F for ascii chars, $7F for delete, $08 for BACKSPACE, $0D for
  1725.    RETURN, $1B for ESCAPE, $010C for LEFT Cursor, $010D for Right Cursor,
  1726.    $020C for SHIFT-LEFT Cursor, and $020D for SHIFT-RIGHT Cursor.
  1727.    UserEntry will continue calling your RawCode for each char, and terminate
  1728.    upon receiving an $0D or $1B, or reaching the charlimit.
  1729.    Since the titlebar can hold approx 70 chars between the CLOSEGADGET and
  1730.    FRONT/BACK, the FileIO's Buffer might be set to 70 bytes. It must be at
  1731.    least as big as charlimit. Upon return, your window's title is restored.
  1732.  
  1733. INPUTS
  1734.    Window = the address of a window
  1735.    FileIO = the FileIO structure
  1736.    charlimit = the number of characters to accept from the user
  1737.    initBuffer = the NULL-terminated string to initialize the FileIO's
  1738.              buffer to, or NULL if no initialization desired
  1739.  
  1740. RESULT
  1741.    Returns the address of the FileIO's Buffer or a 0 if the user bailed
  1742.    out without entering anything. An ESC will return 0, but will store an
  1743.    ESC char ($1B) and then NULL char in the buffer.
  1744.  
  1745.  
  1746. ;******************** PromptUserEntry() ***************************
  1747.  
  1748. NAME
  1749.     PromptUserEntry - Uses the window's titlebar to obtain user input.
  1750.  
  1751. SYNOPSIS
  1752.     buffer = PromptUserEntry(charlimit,prompt,initBuffer,FileIO,Window);
  1753.                                  d0      a0      a1        a2     a3
  1754.  
  1755. FUNCTION
  1756.    This works just like UserEntry except that it first displays the
  1757.    passed prompt string in the titlebar. The FileIO's Buffer should always
  1758.    be greater than the number of chars in the prompt plus charlimit.
  1759.  
  1760. INPUTS
  1761.     Window = the address of a window
  1762.     FileIO = the FileIO structure
  1763.     charlimit = the number of characters to accept from the user
  1764.     buffer = the buffer where the user's input is placed
  1765.     prompt = NULL-terminated prompt to display
  1766.     initBuffer = the NULL-terminated string to initialize the FileIO's
  1767.              buffer to, or 0 if no initialization desired
  1768.  
  1769. RESULT
  1770.   Returns the address of the FileIO's Buffer or a 0 if the user bailed
  1771.   out without entering anything. An ESC will return 0, but will store an
  1772.   ESC char ($1B) and NULL char in the buffer.
  1773.  
  1774.  
  1775. ******************* SetTitle() ********************************
  1776.  
  1777. NAME
  1778.    SetTitle - Uses the window's titlebar to display 1 or 2 strings.
  1779.  
  1780. SYNOPSIS
  1781.     SetTitle(String1,String2,FileIO,Window);
  1782.                a0      a1      a2     a3
  1783.  
  1784. INPUTS
  1785.     Window = the address of a window
  1786.     FileIO = the FileIO structure
  1787.     String1 = the NULL-terminated string to the left
  1788.     String2 = NULL-terminated string placed to the right of String1. If you
  1789.               pass a zero instead, no 2nd string displayed.
  1790.  
  1791. FUNCTION
  1792.   This will display the 2 strings in the window's titlebar (saving the
  1793.   initial title to the FileIO's Title field), and return immediately with
  1794.   the strings still displayed. Subsequent calls can be made to display
  1795.   different strings, but when ResetTitle() is finally called, the initial
  1796.   titlebar is restored. This routine is useful for displaying error msgs to
  1797.   the user without halting program execution (like a requester does), and
  1798.   allows the msg to remain visible for as long as it is needed. Furthermore,
  1799.   it doesn't require that the user respond to it. This function makes temp-
  1800.   orary use of the FileIO's Buffer, so you must supply a buffer whose address
  1801.   is stored at the FileIO Buffer field. This buffer must be large enough to
  1802.   contain both Strings.
  1803.  
  1804.  
  1805. ******************* ResetTitle() ********************************
  1806.  
  1807. NAME
  1808.    ResetTitle - Restores the window's titlebar after calls to SetTitle
  1809.                 (if any calls were made at all)
  1810.  
  1811. SYNOPSIS
  1812.     ResetTitle(FileIO,Window);
  1813.                  a2     a3
  1814.  
  1815. INPUTS
  1816.     Window = the address of a window
  1817.     FileIO = the FileIO structure
  1818.  
  1819. FUNCTION
  1820.     Resets the initial title (stored in FileIO's Title field) if it detects
  1821.     that any calls were made to SetTitle. Otherwise, it does nothing.
  1822.  
  1823.  
  1824. ««««««««««««««««««««««««««««««« CUSTOM LISTS »»»»»»»»»»»»»»»»»»»»»»»»»»»»»»
  1825.  
  1826. ******************* AddEntry() ***********************
  1827.  
  1828. NAME
  1829.   AddEntry - For adding a string to be displayed in the FileIO's FileList
  1830.  
  1831. SYNOPSIS
  1832.   ID_num = AddEntry(ID_num, String, FileIO);
  1833.     d0                d1      a0     a1
  1834.  
  1835. INPUTS
  1836.    The FileIO structure
  1837.    The address of a NULL-terminated string to become the EntryString.
  1838.    A ULONG (or LONG if you define it that way) that is associated with the
  1839.      string.
  1840.  
  1841. FUNCTION
  1842.    When the SPECIAL_REQ flag of the FileIO is set, then DoFileIO() and DoFile-
  1843. IOWindow() no longer do disk operations. Instead, the FileIO's FileList is
  1844. list of FileEntry structures which you create via AddEntry(). The passed
  1845. string becomes the EntryString and the passed ID_num is the EntryID.
  1846.  
  1847. RETURN
  1848.    This returns the passed ID_num if the string was added to the FileIO's
  1849. FileList, or a -2 if no mem to add the string.
  1850.  
  1851.  
  1852. ******************* ClearEntries() ***********************
  1853.  
  1854. NAME
  1855.   ClearEntries - For de-selecting all of the FileIO FileList's FileEntries
  1856.  
  1857. SYNOPSIS
  1858.   ClearEntries(FileIO);
  1859.                  a1
  1860.  
  1861. INPUTS
  1862.    The FileIO structure
  1863.  
  1864. FUNCTION
  1865.    This clears bit #7 of EntryFlags for all the FileEntry structures in the
  1866.    FileIO's FileList. This may be useful for clearing selections after you
  1867.    have processed MULTIPLE_FILES within a custom list (SPECIAL_REQ).
  1868.  
  1869. RETURN
  1870.    NONE
  1871.  
  1872.  
  1873. ******************* NewEntryList() ***********************
  1874.  
  1875. NAME
  1876.   NewEntryList - For freeing any previous FileIO FileList and resetting the
  1877.                  FileIO variables.
  1878.  
  1879. SYNOPSIS
  1880.   NewEntryList(FileIO);
  1881.                  a1
  1882.  
  1883. INPUTS
  1884.    The FileIO structure
  1885.  
  1886. FUNCTION
  1887.    This deletes the FileIO's FileList (i.e. all of the FileEntry structures
  1888.    created with AddEntry).
  1889.  
  1890. RETURN
  1891.    NONE
  1892.  
  1893.  
  1894. ******************* RetrieveEntry() ***********************
  1895.  
  1896. NAME
  1897.   RetrieveEntry - For locating the next selected FileEntry structure within
  1898.                   the FileIO's FileList. (Used with MULTIPLE_FILES selection).
  1899.  
  1900. SYNOPSIS
  1901.   FileEntry = RetrieveEntry(FileEntryPtr, FileIO);
  1902.       d0                         a0         a1
  1903.  
  1904. INPUTS
  1905.    The FileIO structure
  1906.    A PTR (the address) to a FileEntry structure within the FileIO's FileList
  1907.    or a cleared PTR.
  1908.  
  1909. FUNCTION
  1910.    When the MULTIPLE_FILES flag of the FileIO is set, then the library sets
  1911. bit #7 of the EntryFlags of every FileEntry that the user selected. This
  1912. routine helps you locate which files were selected, one at a time. The first
  1913. time that you call this function, FileEntryPtr should be cleared so that the
  1914. function will start at the first FileEntry in the FileIO's FileList.
  1915.  
  1916. RETURN
  1917.   This routine updates FileEntryPtr to point to the next selected FileEntry
  1918. structure, and returns this address. If there is no next selected file, a 0 is
  1919. returned, and FileEntryPtr is cleared. If a FileEntryPtr not equal to 0 is
  1920. returned, you can access the FileEntry's Entry structure to get the EntryID and
  1921. EntryString. This are the FileSize and Filename, respectively. If SPECIAL_REQ
  1922. set, these are the ID and string, respectively.
  1923.  
  1924.  
  1925.  
  1926. «««««««««««««««««««««««««««««« MISC ROUTINES »»»»»»»»»»»»»»»»»»»»»»»»»»»»»»
  1927.  
  1928. ************************* AutoFileMessage() ****************************
  1929.  
  1930. NAME
  1931.     AutoFilemessage - AutoMessage with preset strings to choose from
  1932.  
  1933.  
  1934. SYNOPSIS
  1935.     BOOL AutoFileMessage(messagenumber, window);
  1936.                             d1             a0
  1937.  
  1938. FUNCTION
  1939.     The requester library has several messages it uses for internal use.
  1940.     You can have one of these messages displayed just by passing the number
  1941.     of the message you want. See Include file for available messages.
  1942.     Some of the messages have two responses "YES" and "OK". Others have just
  1943.     the "OK".
  1944.  
  1945. INPUTS
  1946.     window = the address of a window structure
  1947.     messagenumber = number of the string to be displayed
  1948.  
  1949. RESULT
  1950.     Returns FALSE (d0 = 0) if the user selects "NO" or TRUE (d0 = 1) if the
  1951.     user selects "OK".
  1952.  
  1953.  
  1954. ******************** AutoMessage(), AutoMessageLen() ********************
  1955.  
  1956. NAME
  1957.     Automessage - an easy implementation of an AutoRequester
  1958.  
  1959.  
  1960. SYNOPSIS
  1961.      AutoMessage(message, window);
  1962.                    d0       a0
  1963.      AutoMessageLen(message, window, length);
  1964.                       d0       a0      d1
  1965.  
  1966. FUNCTION
  1967.     This displays the passed string (whose address is in d0) in a simple
  1968.     AutoRequester. It manages the dimensions (automatically sizes to the
  1969.     passed message) and the IntuiText structure for you. Use AutoMessageLen
  1970.     if you know the length of the string to be displayed.
  1971.  
  1972. INPUTS
  1973.     window = the address of a window structure
  1974.     message = address of the string to be displayed
  1975.  
  1976. RESULT
  1977.     None
  1978.  
  1979.  
  1980. ************************ AutoPrompt3() **************************
  1981.  
  1982. NAME
  1983.     AutoPrompt3 - AutoRequester with up to 3 lines of Text
  1984.  
  1985.  
  1986. SYNOPSIS
  1987.     BOOL AutoPrompt3(message1, message2, message3, window);
  1988.                         a1        a2       a3        a0
  1989.  
  1990. FUNCTION
  1991.     Displays up to 3 passed strings in an autorequester. Automatically
  1992.     dimensions the requester to the size of the longest string, and
  1993.     positions the other strings for a symmetrical display. Returns with
  1994.     user's response to "YES" or "NO". You can also display only 2 or even
  1995.     1 string if you pass NULL for the other messages.
  1996.  
  1997. INPUTS
  1998.     window = the address of a window structure
  1999.     message1 = address of the top string to be displayed
  2000.     message2 = address of the 2nd string to be displayed or NULL if none
  2001.     message3 = address of the 3nd string to be displayed or NULL if none
  2002.  
  2003. RESULT
  2004.     Returns FALSE (d0 = 0) if the user selects "NO" or TRUE (d0 = 1) if the
  2005.     user selects "YES".
  2006.  
  2007.  
  2008. ************************ ResetBuffer() *********************************
  2009.  
  2010. NAME
  2011.     ResetBuffer - Resets the cursor within a StringInfo's buffer to the
  2012.                   first position. Also, can NULL out the buffer itself and
  2013.                   reset the number of chars to 0.
  2014.  
  2015.  
  2016. SYNOPSIS
  2017.     ResetBuffer(stringinfo, resetFlag);
  2018.                    a0           d0
  2019.  
  2020. FUNCTION
  2021.     If you have a String gadget whose cursor you'd like to set back at the
  2022.     first position, you can use this function. Also, if resetFlag is TRUE
  2023.     (1) then the gadget's buffer will be NULLED. You must refresh the gadget
  2024.     yourself after this call.
  2025.  
  2026. INPUTS
  2027.     stringinfo = the address of a StringInfo structure
  2028.     resetFlag = whether to NULL or not
  2029.  
  2030. RESULT
  2031.     NONE
  2032.  
  2033.  
  2034. ************************** SetWaitPointer() *************************
  2035.  
  2036. NAME
  2037.     SetWaitPointer - Sets the zzz cloud pointer in the passed window.
  2038.  
  2039.  
  2040. SYNOPSIS
  2041.     SetWaitPointer(window);
  2042.                     a0
  2043.  
  2044. FUNCTION
  2045.     If you want to have a wait pointer appear in a window, you can use this
  2046.     function which already has set up the pointer data in CHIP mem. Then
  2047.     when you want to restore the pointer, call Intuition's ClearPointer().
  2048.  
  2049. INPUTS
  2050.     window = the address of a window structure
  2051.  
  2052. RESULT
  2053.     None
  2054.